Next | Prev | Up | Top | Contents | Index

Using Command-Building Functions

The remaining functions in dslib each construct and execute a specific type of common SCSI command. Each function follows this general pattern:

  1. Use fillg0cmd() or fillg1cmd() to set up the command string, based on the function's arguments.

  2. Use filldsreq() to set up the remaining fields of the dsreq structure.

  3. Execute the command using doscsireq().

  4. Return the value returned by doscsireq().
You can construct similar, additional functions using the utility functions in this same way. In particular you are likely to need to construct your own function to issue Read commands.


inquiry12()--Issue an Inquiry Command

The inquiry12() function prepares and issues an Inquiry command to retrieve device-specific information. The function prototype is

int inquiry12(struct dsreq *dsp, caddr_t data, long datalen, int vu);

The arguments are as follows:

dsp The address of a dsreq structure prepared by dsopen().
data The address of a buffer to receive the inquiry response.
datalen The length of the buffer, at least 36 and typically 64.
vu The least-significant two bits are used to set the vendor-specific bits in the Control byte in the command.


modeselect15()--Issue a Group 0 Mode Select Command

The modeselect15() function prepares and issues a group 0 Mode Select command. This command is used to control a variety of standard and vendor-specific device parameters. Typically, modesense1A() is first used to retrieve the current parameters. The function prototype is

int modeselect15(struct dsreq *dsp, caddr_t data, long datalen, int save, int vu);

The arguments are as follows:

dsp The address of a dsreq structure prepared by dsopen().
data The address of a mode data page to send.
datalen The length of the data.
save The least significant bit sets the SP bit in the command.
vu The least-significant two bits are used to set the vendor-specific bits in the Control byte in the command.


modesense1a()--Send a Group 0 Mode Sense Command

The modesense1a() function prepares and issues a group 0 Mode Sense command to a SCSI device to retrieve a page of device-dependent information. The function prototype:

int modesense1a(struct dsreq *dsp, caddr_t data, long datalen, int pagectrl, int pagecode, int vu);

The arguments are as follows:

dsp The address of a dsreq structure prepared by dsopen().
data The address of a buffer to receive the page of data.
datalen The length of the buffer.
pagectrl The least significant 2 bits are set as the PCF bits in the command.
pagecode The least significant 6 bits are set as the page number.
vu The least-significant two bits are used to set the vendor-specific bits in the Control byte in the command.

For reference, the PCF codes are as follows:

0Current values.
1Changeable values.
2Default values.
3Saved values.

For reference, some page numbers are as follows:

0Vendor unique.
1Read/write error recovery.
2Disconnect/reconnect.
3Direct access device format; parallel interface; measurement units.
4Rigid disk geometry; serial interface.
5Flexible disk; printer options.
6Optical memory.
7Verification error.
8Caching.
9Peripheral device.
63 (0x3f)Return all pages supported.


read08() and readextended28()--Issue a Read Command

The read08() and readextended28() functions prepare and issue particular forms of SCSI Read commands. The Read and extended Read commands have so many variations that it is unlikely that either of these functions will work with your device. However, you can use them as models to build additional variations on Read. Do not preempt the function names.

The function prototypes are

int
read08(struct dsreq *dsp, caddr_t data, long datalen,
              long lba, int vu);
int
readextended28(struct dsreq *dsp, caddr_t data, long datalen,
              long lba, int vu);
The arguments are as follows:

dsp The address of a dsreq structure prepared by dsopen().
data The address of a buffer to receive the data.
datalen The length of the buffer (not exceeding 255 for read08)
lba The logical block address for the start of the read (not exceeding 16 bits for read08)
vu The least-significant two bits are used to set the vendor-specific bits in the Control byte in the command.

The functions set the transfer length in the command to the number of bytes given by datalen. This is often incorrect; many devices want a number of blocks of some size. Function read08() sets only 16 bits from lba as the logical block number, although the SCSI command format permits another 5 bits to be encoded in the command. For these and other reasons you are likely to need to create customized Read functions of your own.


readcapacity25()--Issue a Read Capacity Command

The readcapacity25() function prepares and issues a Read Capacity command to a SCSI device. The function prototype is

int readcapacity25(struct dsreq *dsp, caddr_t data, long datalen, long lba, int pmi, int vu);

The arguments are as follows:

dsp The address of a dsreq structure prepared by dsopen().
data The address of a buffer to receive the capacity data.
datalen The length of the buffer, typically 8.
lba Last block address, 0 unless pmi is nonzero.
pmi The least-significant bit is used to set the partial medium indicator (PMI) bit of the command.
vu The least-significant two bits are used to set the vendor-specific bits in the Control byte in the command.

When pmi is 0, lba should be given as 0 and the command returns the device capacity. When pmi is 1, the command returns the last block following block lba before which a delay (seek) will occur.


requestsense03()--Issue a Request Sense Command

The requestsense03() function prepares and issues a Request Sense command. If you include DSRQ_SENSE in the flag argument to doscsireq(), a Request Sense is sent automatically after an error in a command. The function prototype is

int requestsense03(struct dsreq *dsp, caddr_t data, long datalen, int vu);

The arguments are:

dsp The address of a dsreq structure prepared by dsopen().
data The address of a buffer to receive the sense data.
datalen The length of the buffer.
vu The least-significant two bits are used to set the vendor-specific bits in the Control byte in the command.


reserveunit16() and releaseunit17()--Control Logical Units

The reserveunit16() function prepares and issues a Reserve Unit command to reserve a logical unit, causing it to return Reservation Conflict status to requests from other initiators. The releaseunit17() function prepares and issues a Release Unit command to release a reserved unit. The function prototypes are

int
reservunit16(struct dsreq *dsp, caddr_t data, long datalen,
            int tpr, int tpdid, int extent, int res_id, int vu);
int
releaseunit17(struct dsreq *dsp,
            int tpr, int tpdid, int extent, int res_id, int vu);
The arguments are as follows:

dsp The address of a dsreq structure prepared by dsopen().
data The address of data to send with the Reserve Unit. (This may be NULL for reservunit16() which does not normally transfer data.)
datalen The length of the data (typically 0).
tpr The least-significant bit is used to set the Third-Party Reservation bit in the command: 1 means the reservation is on behalf of another initiator.
tpdid The device ID for the device to hold the reservation: 0 unless tpr is 1.
extent The least-significant bit sets the least-significant bit of byte 1 of the command string.
res_id Passed as byte 2 of the command string.
vu The least-significant two bits are used to set the vendor-specific bits in the Control byte in the command.


senddiagnostic1d()--Issue a Send Diagnostic Command

The senddiagnostic1d() function prepares and issues a Send Diagnostic command. The function prototype is

int senddiagnostic1d(struct dsreq *dsp, caddr_t data, long datalen, int self, int dofl, int uofl, int vu);

The arguments are as follows:

dsp The address of a dsreq structure prepared by dsopen().
data The address of a page or pages of diagnostic parameter data to be sent.
datalen The length of the data (0 if none).
self The least-significant bit sets the Self Test (ST) bit in the command: 1 means return status from the self-test; 0 means hold the results.
dofl The least-significant bit sets the Device Offline bit of the command: 1 authorizes tests that can change the status of other logical units.
uofl The least-significant bit sets the Unit Offline bit of the command: 1 authorizes tests that can change the status of the logical unit.
vu The least-significant two bits are used to set the vendor-specific bits in the Control byte in the command.

When self is 1, the status reflects the success of the self-test. You should either set the DSRQ_SENSE flag in the dsreq so that if the self-test fails, a Sense command will be issued, or be prepared to call requestsense03(). When self is 0, you can use a Read Diagnostic command to return detailed results of the test (however, dslib does not contain a predefined function for Read Diagnostic).


testunitready00--Issue a Test Unit Ready Command

The testunitready00() function prepares and issues a Test Unit Ready command to a SCSI device. The function prototype is

int testunitready00(struct dsreq *dsp);

This function is reproduced here in Example 5-2 as an example of how other command-oriented functions can be created.

Example 5-2 : Code of the testunitread00() Function

int
testunitready00(struct dsreq *dsp)
{
   fillg0cmd(dsp, CMDBUF(dsp), G0_TEST, 0, 0, 0, 0, 0);
   filldsreq(dsp, 0, 0, DSRQ_READ|DSRQ_SENSE);
   return(doscsireq(getfd(dsp), dsp));
}

write0a() and writeextended2a()--Issue a Write Command

The write0a() function prepares and issues a group 0 Write command. The writeextended2a() function prepares and issues an extended (10-byte) Write command. As with Read commands (see "read08() and readextended28()--Issue a Read Command"), Write commands have many device-specific features, and you will very likely have to create your own customized version of these functions.

The function prototypes are

int
write0a(struct dsreq *dsp, caddr_t data, long datalen,
        long lba, int vu);
int
writeextended2a(struct dsreq *dsp, caddr_t data, long datalen,
        long lba, int vu);
The arguments are as follows:

dsp The address of a dsreq structure prepared by dsopen().
data The address of the data to be sent.
datalen The length of the data (at most 255 for write0a)
lba The logical block address (at most 16 bits for write0a)
vu The least-significant two bits are used to set the vendor-specific bits in the Control byte in the command.


Next | Prev | Up | Top | Contents | Index